/* * Copyright 2016 higherfrequencytrading.com * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package net.openhft.performance.tests.third.party.frameworks.netty; import io.netty.bootstrap.Bootstrap; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.netty.channel.*; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.channel.socket.SocketChannel; import io.netty.channel.socket.nio.NioSocketChannel; import io.netty.handler.ssl.SslContext; import io.netty.handler.ssl.util.InsecureTrustManagerFactory; import io.netty.util.ReferenceCountUtil; import net.openhft.performance.tests.vanilla.tcp.EchoClientMain; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import javax.net.ssl.SSLException; import java.util.Arrays; import java.util.concurrent.TimeUnit; /** * Sends one message when a connection is open and echoes back any received data to the server. * Simply put, the echo client initiates the ping-pong traffic between the echo client and server by * sending the first message to the server. */ public final class NettyClientThroughPutTest { static final boolean SSL = System.getProperty("ssl") != null; static final String HOST = System.getProperty("host", "127.0.0.1"); static final int PORT = Integer.parseInt(System.getProperty("port", Integer.toString(EchoClientMain .PORT))); static class MyChannelInboundHandler extends ChannelInboundHandlerAdapter { private final ByteBuf firstMessage; final int bufferSize = 32 * 1024; @NotNull byte[] payload = new byte[bufferSize]; long bytesReceived = 0; long startTime; int i = 0; { Arrays.fill(payload, (byte) 'X'); firstMessage = Unpooled.buffer(bufferSize); firstMessage.writeBytes(payload); } @Override public void channelActive(@NotNull ChannelHandlerContext ctx) { startTime = System.nanoTime(); ctx.writeAndFlush(firstMessage); System.out.print("Running throughput test ( for 10 seconds ) "); } @Override public void channelRead(@NotNull ChannelHandlerContext ctx, @NotNull Object msg) { try { bytesReceived += ((ByteBuf) msg).readableBytes(); if (i++ % 10000 == 0) System.out.print("."); if (TimeUnit.NANOSECONDS.toSeconds(System .nanoTime() - startTime) >= 10) { long time = System.nanoTime() - startTime; System.out.printf("\nThroughput was %.1f MB/s%n", 1e3 * bytesReceived / time); return; } } finally { ReferenceCountUtil.release(msg); // (2) } final ByteBuf outMsg = ctx.alloc().buffer(bufferSize); // (2) outMsg.writeBytes(payload); ctx.writeAndFlush(outMsg); // (3) } @Override public void channelReadComplete(@NotNull ChannelHandlerContext ctx) { ctx.flush(); } @Override public void exceptionCaught(@NotNull ChannelHandlerContext ctx, @NotNull Throwable cause) { // Close the connection when an exception is raised. cause.printStackTrace(); ctx.close(); } } public static void main(String[] args) throws SSLException, InterruptedException { // Configure SSL.git @Nullable final SslContext sslCtx; if (SSL) { sslCtx = SslContext.newClientContext(InsecureTrustManagerFactory.INSTANCE); } else { sslCtx = null; } // Configure the client. @NotNull EventLoopGroup group = new NioEventLoopGroup(); try { @NotNull Bootstrap b = new Bootstrap(); b.group(group) .channel(NioSocketChannel.class) .option(ChannelOption.TCP_NODELAY, true) .handler(new ChannelInitializer<SocketChannel>() { @Override public void initChannel(@NotNull SocketChannel ch) { ChannelPipeline p = ch.pipeline(); if (sslCtx != null) { p.addLast(sslCtx.newHandler(ch.alloc(), HOST, PORT)); } //p.addLast(new LoggingHandler(LogLevel.INFO)); p.addLast(new MyChannelInboundHandler()); } }); // Start the client. ChannelFuture f = b.connect(HOST, PORT).sync(); // Wait until the connection is closed. f.channel().closeFuture().sync(); } finally { // Shut down the event loop to terminate all threads. group.shutdownGracefully(); } } }